﻿using System;
using NUnit.Framework;
using Rhino.Mocks;
using System.Data;
using EventHandler.Libraries.Business.Event;
using EventHandler.Libraries.Business.Database;

namespace EventHandler.Libraries.Business.Tests.Event
{
    [TestFixture]
    public class CreateEventTest
    {
        private static IDatabaseHelper CreateDatabaseHelper()
        {
            return MockRepository.GenerateMock<IDatabaseHelper>();
        }
        private static ICreateEventItem GetValidCreateEventItem()
        {
            ICreateEventItem newEvent = new CreateEventItem
            {
              Title = "Title",
              OwnerId = 1
            };
            return newEvent;
        }
        private static ICreateEventItem GetInvalidCreateEventItem()
        {
            ICreateEventItem newEvent = new CreateEventItem
            {
                Title = "",
                OwnerId = -1
            };
            return newEvent;
        }

        private static void CreateEventItem(ICreateEventItem testEventItem)
        {
            IDatabaseHelper dbHelper = CreateDatabaseHelper();
            var helper = new EventItemHelper(dbHelper);

            var cn = MockRepository.GenerateMock<IDbConnection>();
            dbHelper.Expect(x => x.GetConnection()).Return(cn);

            var cmd = MockRepository.GenerateMock<IDbCommand>();
            cn.Expect(x => x.CreateCommand()).Return(cmd);
            cmd.Expect(x => x.CommandText).PropertyBehavior();
            cmd.Expect(x => x.CommandType).PropertyBehavior();

            var parameters = MockRepository.GenerateMock<IDataParameterCollection>();
            cmd.Expect(x => x.Parameters).Return(parameters).Repeat.Any();

            var titleParameter = MockRepository.GenerateMock<IDbDataParameter>();
            cmd.Expect(x => x.CreateParameter()).Return(titleParameter);
            titleParameter.Expect(x => x.Size).PropertyBehavior();
            titleParameter.Expect(x => x.ParameterName).PropertyBehavior();
            titleParameter.Expect(x => x.Value).PropertyBehavior();
            titleParameter.Expect(x => x.DbType).PropertyBehavior();
            var ownerIdParameter = MockRepository.GenerateMock<IDbDataParameter>();
            cmd.Expect(x => x.CreateParameter()).Return(ownerIdParameter);
            ownerIdParameter.Expect(x => x.ParameterName).PropertyBehavior();
            ownerIdParameter.Expect(x => x.Value).PropertyBehavior();
            ownerIdParameter.Expect(x => x.DbType).PropertyBehavior();
            var eventIdParameter = MockRepository.GenerateMock<IDbDataParameter>();
            cmd.Expect(x => x.CreateParameter()).Return(eventIdParameter);
            eventIdParameter.Expect(x => x.ParameterName).PropertyBehavior();
            eventIdParameter.Expect(x => x.Direction).PropertyBehavior();
            eventIdParameter.Expect(x => x.DbType).PropertyBehavior();
            eventIdParameter.Expect(x => x.Value).Return(1);

            int result = helper.CreateEvent(testEventItem);

            cn.AssertWasCalled(x => x.Open());
            cn.AssertWasCalled(x => x.Close());

            Assert.AreEqual(result, 1);

            Assert.AreEqual("Event.CreateNewEvent", cmd.CommandText);
            Assert.AreEqual(CommandType.StoredProcedure, cmd.CommandType);

            Assert.AreEqual("@EventTitle", titleParameter.ParameterName);
            Assert.AreEqual(testEventItem.Title, titleParameter.Value);
            Assert.AreEqual(255, titleParameter.Size);
            Assert.AreEqual(DbType.String, titleParameter.DbType);
            Assert.AreEqual("@OwnerId", ownerIdParameter.ParameterName);
            Assert.AreEqual(testEventItem.OwnerId, ownerIdParameter.Value);
            Assert.AreEqual(DbType.Int32, ownerIdParameter.DbType);
            Assert.AreEqual("@EventId", eventIdParameter.ParameterName);
            Assert.AreEqual(DbType.Int32, eventIdParameter.DbType);
            Assert.AreEqual(ParameterDirection.Output, eventIdParameter.Direction);
        }

        [Test]
        public void TestEventCreation()
        {
            CreateEventItem(GetValidCreateEventItem());
        }
        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void TestInvalidEventItem()
        {
            CreateEventItem(GetInvalidCreateEventItem());
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void TestEventItemIsNull()
        {
            CreateEventItem(null);
        }
    }
}
